package org.jederik.studip.android.view;

import org.jederik.android.provider.StudIP;
import org.jederik.android.provider.StudIP.Feed;
import org.jederik.android.provider.StudIP.Messages;
import org.jederik.studip.android.Const;
import org.jederik.studip.android.R;
import org.jederik.studip.android.sync.CheckChangesService;
import org.jederik.studip.android.sync.SyncService;
import org.jederik.studip.android.view.tools.FeedAdapter;

import android.app.ListActivity;
import android.app.NotificationManager;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.database.ContentObserver;
import android.database.Cursor;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.Window;
import android.widget.ListView;

/**
 * Diese Activity zeigt eine Liste der neuesten, den Nutzer betreffenden Änderungen
 * in Stud.IP an.
 * @author Jann-Frederik Laß
 */
public class FeedActivity extends ListActivity {
	
	private static final String TAG = "FeedActivity";

	
	public static final String REMOVE_NOTIFICATIONS = "remove_notifications";

	// Darzustellender Inhalt:
	private Cursor cursor = null;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        
        // Ladesymbol in der Titelleiste anfordern (noch nicht anzeigen):
        requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
        
        setContentView(R.layout.feed);
        getListView().setEmptyView(findViewById(R.id.empty));

        // Ansicht Laden:
        setListAdapter(null);
        
    }
    
	@Override
	protected void onDestroy() {
		super.onDestroy();
		
		// Falls vom Nutzer so eingestellt, wird der Hintergrundservice gestartet
		boolean checkChanges = Preferences
									.getPreferences(this)
									.getBoolean(Preferences.CHECK_CHANGES, false);
		Intent i = new Intent(
				getApplicationContext(),
				CheckChangesService.class);
		if (checkChanges) startService(i);
		else stopService(i);
		
	}

	/** Wird benachrichtigt, wenn die lokalen Daten geändert werden. */
	private final ContentObserver mContentObserver = new ContentObserver(new Handler()) {

		@Override
		public void onChange(boolean selfChange) {
			loadContent();
		}
		
	};
	
	@Override
	protected void onResume() {
		super.onResume();
		
		// Für Benachrichtigungen über Änderungen der lokalen Daten registreiren:
		getContentResolver().registerContentObserver(
				Feed.CONTENT_URI, 
				false, 
				mContentObserver
		);

		// Daten von lokaler Datenbank laden und anzeigen:
		loadContent();
		
		// Ggf. Notification aus der Statusleiste entfernen:
		if (getIntent().getBooleanExtra(REMOVE_NOTIFICATIONS, false)) {
			Log.d(TAG, "REMOVE_NOTIFICATUIONS");
			removeNotifications();
		}
	}

	@Override
	protected void onPause() {
		super.onPause();
		
		// ContentObserver entfernen:
		getContentResolver().unregisterContentObserver(mContentObserver);
		
	}

	/** Initiiert den Synchronisationsvorgang. */
    private void synchronize() throws RemoteException {

		// Ladesymbol angezeigen:
        setProgressBarIndeterminateVisibility(true);

        Intent sync = new Intent(Intent.ACTION_SYNC, StudIP.CONTENT_URI);
        sync.putExtra(SyncService.CALLBACK_MESSENGER, mCallbackMessenger);
        startService(sync);
        
    }

    /**
     * Nimmt die Callbacks vom SyncService entgegen und behandelt die 
     * Rückmeldung.
     */
    private final Messenger mCallbackMessenger = new Messenger(new Handler() {
		@Override
		public void handleMessage(Message msg) {
			// Ladesymbol ausblenden:
	        setProgressBarIndeterminateVisibility(false);
		}
    });
    
	@Override
	protected void onListItemClick(ListView l, View v, int position, long id) {
		
		// Cursor zum ausgewählten Eintrag bewegen:
		cursor.moveToPosition(position);
		
		// Typ und ID der Resource auslesen, auf die sich der Eintrag bezieht:
		String objectType = cursor.getString(cursor.getColumnIndex(Feed.OBJECT_TYPE));
		String objectId = cursor.getString(cursor.getColumnIndex(StudIP.OBJECT_ID));

		// Versuchen, die Resource anzuzeigen:
		Intent i = new Intent(
				Intent.ACTION_VIEW, 
				Uri.withAppendedPath(StudIP.defaultUris.get(objectType), objectId)
		);
		startActivity(i);
	}
	
	/** Entfernt die Notifications aus der Status-Leiste des Betriebssystems */
	private void removeNotifications() {
		
		Log.d(TAG, "removeNotifications()");
		
		NotificationManager nm =
			(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
		
		nm.cancel(Const.NOTIFICATION_ID);
		
		
	}
	
	/** Lädt den Inhalt in einem extra Thread */
	private class Loader extends AsyncTask<Object, Object, Cursor> {

		@Override
		protected Cursor doInBackground(Object... params) {
			
			// Inhalt von lokaler Datenbank laden:
			return managedQuery(Feed.CONTENT_URI, null, null, null, null);
		}

		@Override
		protected void onPostExecute(Cursor result) {
			
			Log.d(TAG, "loadContent()");
			
			if (result == null || result.isClosed()) return;

			
			// Neuen FeedAdapter als ListAdapter übergeben:
			setListAdapter(new FeedAdapter(
					FeedActivity.this, 
					result
			));

			// Ergebnis merken:
			cursor = result;
			
			// In den Einstellung das Änderungsdatum des aktuellsten
			// Eintrags speichern:
			if (result.getCount() == 0) return;
			result.moveToFirst();
			int lastFeedView = result.getInt(result.getColumnIndex(Feed.DATE));
			SharedPreferences.Editor editor = 
				getSharedPreferences(Const.PREFS_NAME, 0).edit();
			editor.putInt(Preferences.LAST_FEED_VIEW, lastFeedView);
			editor.commit();

		}
	};
	
	/** Zeigt die geladenen Daten im List View an. */
	private void loadContent() {

		// Der Zugriff auf den ContentResolver findet in einem extra Thread statt:
		new Loader().execute(Feed.CONTENT_URI);
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		super.onCreateOptionsMenu(menu);
		
		// Menü laden:
		MenuInflater mi = new MenuInflater(getApplication());
		mi.inflate(R.menu.feed, menu);
		
		return true;
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {

		// Durch eine Fallunterscheidung wird ermittelt, welche Menüauswahl
		// getroffen wurde und die entsprechende Aktion durchgeführt.
		
		Intent i;
		switch (item.getItemId()) {
		case R.id.menu_preferences:
			// Einstellungen anzeigen:
			i = new Intent(this, Preferences.class);
			startActivity(i);
			return true;
			
		case R.id.menu_reload:
			// Ansicht aktualisieren:
			try {
				synchronize();
			} catch (RemoteException e) {
				// TODO Dialog anzeigen
				e.printStackTrace();
			}
			return true;
			
		case R.id.menu_message:
			// Nachricht schreiben:
			i = new Intent(Intent.ACTION_SEND, Messages.CONTENT_URI);
			startActivity(i);
			return true;
			
		case R.id.menu_mycourses:
			// Nachricht schreiben:
			i = new Intent(this, MycoursesActivity.class);
			startActivity(i);
			return true;
		}
		
		return super.onOptionsItemSelected(item);
		
	}
}